﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using EstimatesTool.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;

namespace EstimatesTool.ViewModel;

public partial class MainViewModel : ObservableValidator
{
    public List<string> Infos { get; set; }

    [ObservableProperty]
    [Required(ErrorMessage = "Input Folder is empty..")]
    private string txtIn;

    [ObservableProperty]
    [Required(ErrorMessage = "Output Folder is empty..")]
    private string txtOut;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(Visbly))]
    private bool similarity;

    [ObservableProperty]
    private bool other;

    [ObservableProperty]
    [Range(80, 100)]
    private int percentage;

    [ObservableProperty]
    private Visibility isRunning;

    [ObservableProperty]
    private int num;

    public Visibility Visbly
    {
        get
        {
            if (Similarity) return Visibility.Visible;
            else return Visibility.Hidden;
        }
    }


    public MainViewModel()
    {
        Infos = [];
        TxtIn = string.Empty;
        TxtOut = string.Empty;
        percentage = 80;
        Other = true;
        IsRunning = Visibility.Hidden;
    }

    partial void OnTxtInChanged(string value)
    {
        SubClear();
    }

    private void SubClear()
    {
        Infos.Clear();
        Similarity = false;
        Other = true;
        Num = 0;
    }

    [RelayCommand]
    public void InPath()
    {
        var fd = new FolderBrowserDialog();
        DialogResult dr = fd.ShowDialog();
        if (dr == DialogResult.OK) TxtIn = fd.SelectedPath;
    }

    [RelayCommand]
    public void OutPath()
    {
        var fd = new FolderBrowserDialog();
        DialogResult dr = fd.ShowDialog();
        if (dr == DialogResult.OK) TxtOut = fd.SelectedPath;
    }

    [RelayCommand]
    public void Clear()
    {
        TxtIn = string.Empty;
        TxtOut = string.Empty;
        Percentage = 80;
        SubClear();
    }

    [RelayCommand]
    public async Task TotalCount()
    {
        ValidateProperty(TxtIn, nameof(TxtIn));
        ValidateProperty(TxtOut, nameof(TxtOut));
        if (Similarity) ValidateProperty(Percentage, nameof(Percentage));
        if (HasErrors) return;
        var dir = new DirectoryInfo(TxtIn);
        var files = dir.GetFiles("*.*", SearchOption.AllDirectories).ToList();
        var exts = files.Select(t => Path.GetExtension(t.Name).ToLower()).Distinct().ToList();
        var comm = new CommentUtil(exts);
        comm.Init();
        IsRunning = Visibility.Visible;
        //Infos.AddRange(files.Select(f => string.Format("{0} is OK...", f.FullName)));
        await DoCount(files, comm);
    }

    private Task DoCount(List<FileInfo> files, CommentUtil comm)
    {
        int all = files.Count;
        double idx = 0;
        Num = 0;
        if (Percentage < 80) Percentage = 80;
        var dt = new DataTable();
        dt.Columns.Add("No");
        dt.Columns.Add("Folder");
        dt.Columns.Add("FileName");
        dt.Columns.Add("Extension");
        dt.Columns.Add("Total");
        dt.Columns.Add("Empty");
        dt.Columns.Add("Comment");
        dt.Columns.Add("Rows");
        dt.Columns.Add("Similar File");
        dt.Columns.Add("Percentage");
        Task.Delay(100).ContinueWith(t =>
        {
            foreach (FileInfo file in files)
            {
                idx++;
                var ext = file.Extension.ToLower();
                bool isTxt = FileUtil.IsTextFile(file.FullName);
                if (!isTxt) dt.Rows.Add("", file.DirectoryName, file.Name, ext, 0, 0, 0, 0);
                else
                {
                    var code = FileUtil.GetEncoding(file.FullName);
                    var lines = File.ReadAllLines(file.FullName, code).ToList();
                    int empty = lines.Count(string.IsNullOrEmpty);
                    int total = lines.Count;
                    lines = lines.Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToList();
                    int count = comm.GetCount(ext, lines);
                    int comment = total - empty - count;
                    if (empty == 0 && count == 0)
                    {
                        total = 0;
                        comment = 0;
                    }
                    if (Similarity && count > 0)
                    {
                        var similarFile = FileUtil.LineCompare(files, file, out double percentage);
                        if (percentage * 100 < Percentage)
                        {
                            dt.Rows.Add("", file.DirectoryName, file.Name, ext, total, empty, comment, count, similarFile, percentage);
                        }
                        else dt.Rows.Add("", file.DirectoryName, file.Name, ext, total, empty, comment, count);
                    }
                    else dt.Rows.Add("", file.DirectoryName, file.Name, ext, total, empty, comment, count);
                }
                Num = (int)(idx / all * 100);
            }
            IsRunning = Visibility.Hidden;
            var outfile = ExcelUtil.OutPutSourceList(dt, Similarity, TxtOut);
            InfoUtil.Info($"「{outfile}」\r\nis already created..");
        });
        return Task.CompletedTask;
    }
}